<template>
  <div class="tree-select-container" :style="{ width: totalWidth + 'px' }">
    <!-- 顶部搜索和操作区 -->
    <div class="tree-select-header">
      <a-input
        v-model:value="searchText"
        :placeholder="placeholder"
        class="search-input"
        @change="handleSearch"
        @keyup="handleSearch"
      />
      <div class="operations">
        <button @click="clearSearch" v-if="isSearching">清除搜索</button>
        <button @click="selectAll">全选</button>
        <button @click="clearAll">清空</button>
      </div>
    </div>

    <!-- 搜索结果页 -->
    <div v-if="isSearching && searchText" class="search-results">
      <div class="search-results-header">
        <div class="search-title">
          <span>搜索结果</span>
          <span v-if="allSearchResults.length > 0" class="result-count">({{ allSearchResults.length }})</span>
        </div>
        <span class="close-search" @click="clearSearch">×</span>
      </div>

      <div class="search-results-content">
        <div v-if="allSearchResults.length === 0" class="empty-tip">未找到匹配的结果</div>
        <div v-else>
          <div v-for="(result, index) in allSearchResults" :key="index" class="search-result-item">
            <label class="checkbox-label">
              <a-checkbox :checked="result.selected" @change="toggleSearchResultItem(result)" @click.stop />
              <div class="result-item-content">
                <span class="category-path">{{ result.categoryName }}</span>
                <span v-if="result.isSubItem" class="path-separator">></span>
                <span :class="{ 'highlight': true, 'main-category': !result.isSubItem }">{{ result.name }}</span>
              </div>
            </label>
          </div>
        </div>
      </div>
    </div>

    <!-- 主体内容区 -->
    <div v-if="!isSearching || !searchText" class="tree-content">
      <!-- 动态层级选择区域 -->
      <div class="dynamic-tree-area" :style="{ width: leftAreaWidth + 'px' }">
        <!-- 第一层级 -->
        <div class="tree-column">
          <div
            v-for="item in internalData"
            :key="getNodeId(item)"
            class="category-item"
            :class="{ active: selectedPath[0] === getNodeId(item) }"
            @click="selectCategory(item, 0)"
          >
            <label class="checkbox-label">
              <a-checkbox
                :checked="isNodeSelected(item)"
                :indeterminate="isNodeIndeterminate(item)"
                @change="toggleNodeSelection(item)"
                @click.stop
              />
              {{ getNodeName(item) }}
            </label>
            <span class="arrow" v-if="hasChildren(item)">></span>
          </div>
        </div>

        <!-- 第二层级（如果有） -->
        <div class="tree-column" v-if="level2Items.length > 0">
          <div
            v-for="item in level2Items"
            :key="getNodeId(item)"
            class="category-item"
            :class="{ active: selectedPath[1] === getNodeId(item) }"
            @click="selectCategory(item, 1)"
          >
            <label class="checkbox-label">
              <a-checkbox
                :checked="isNodeSelected(item)"
                :indeterminate="isNodeIndeterminate(item)"
                @change="toggleNodeSelection(item)"
                @click.stop
              />
              {{ getNodeName(item) }}
            </label>
            <span class="arrow" v-if="hasChildren(item)">></span>
          </div>
        </div>

        <!-- 第三层级（如果有） -->
        <div class="tree-column" v-if="level3Items.length > 0">
          <div v-for="item in level3Items" :key="getNodeId(item)" class="category-item">
            <label class="checkbox-label">
              <a-checkbox
                :checked="isNodeSelected(item)"
                :indeterminate="isNodeIndeterminate(item)"
                @change="toggleNodeSelection(item)"
                @click.stop
              />
              {{ getNodeName(item) }}
            </label>
          </div>
        </div>
      </div>

      <!-- 右侧已选择数据区 -->
      <div class="selected-area" :style="{ width: rightAreaWidth + 'px' }">
        <div class="selected-header">
          <div>
            <span>已选择</span>
            <span v-if="totalSelectedCount > 0" class="selected-count">({{ totalSelectedCount }})</span>
          </div>
          <span class="clear-btn" @click="clearAll">清空</span>
        </div>
        <div class="selected-list">
          <div v-if="totalSelectedCount === 0" class="empty-tip">暂无选择项目</div>
          <div v-else class="selected-items">
            <div v-for="(item, index) in flattenSelectedItems" :key="index" class="selected-item">
              <span class="item-name">{{ item.path }}</span>
              <span class="remove-icon" @click.stop="removeSelectedItemByPath(item.path, $event)">×</span>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, computed, watch, onMounted, defineExpose } from "vue";

// 简化类型定义
interface CategoryItem {
  [key: string]: any;
  selected?: boolean;
}

interface SelectedResult {
  category: string;
  items: string[];
}

interface SearchResultItem {
  id: string | number;
  name: string;
  selected: boolean;
  categoryName: string;
  isSubItem: boolean;
  parentRef: CategoryItem;
}

// 定义属性
const props = defineProps({
  data: {
    type: Array as () => CategoryItem[],
    required: true,
    default: () => [],
  },
  placeholder: {
    type: String,
    default: "请输入搜索内容",
  },
  totalWidth: {
    type: Number,
    default: 900,
  },
  rightColumnWidth: {
    type: Number,
    default: 300,
  },
  // 字段映射选项
  idField: {
    type: String,
    default: "id",
  },
  nameField: {
    type: String,
    default: "name",
  },
  childrenField: {
    type: String,
    default: "children",
  },
  // 选择模式：'parent'(父元素优先) 或 'child'(只返回子元素)
  returnMode: {
    type: String,
    default: "parent",
    validator: (value: string) => ["parent", "child"].includes(value),
  },
  // 已选择的值
  selectedIds: {
    type: Array as () => (string | number)[],
    default: () => [],
  },
});

// 计算左侧区域宽度（总宽度减去右侧区域宽度）
const leftAreaWidth = computed(() => props.totalWidth - props.rightColumnWidth);
const rightAreaWidth = computed(() => props.rightColumnWidth);

// 定义事件
const emit = defineEmits(["change"]);

// 响应式状态
const searchText = ref("");
const internalData = ref<CategoryItem[]>([]);
const isSearching = ref(false);
const selectedPath = ref<(string | number | null)[]>([null, null, null]);

// 辅助方法
const getNodeId = (node: CategoryItem) => node[props.idField];
const getNodeName = (node: CategoryItem) => node[props.nameField];
const getNodeChildren = (node: CategoryItem) => node[props.childrenField];
const setNodeSelected = (node: CategoryItem, selected: boolean) => (node.selected = selected);
const hasChildren = (node: CategoryItem) => {
  const children = getNodeChildren(node);
  return children && children.length > 0;
};

// 节点操作
const setNodeSelectionState = (node: CategoryItem, selected: boolean) => {
  setNodeSelected(node, selected);

  const children = getNodeChildren(node);
  if (children && children.length > 0) {
    children.forEach((child: CategoryItem) => setNodeSelectionState(child, selected));
  }
};

// 基础操作
const clearAll = () => {
  internalData.value.forEach((node) => setNodeSelectionState(node, false));
  emitChange();
};

const selectAll = () => {
  internalData.value.forEach((node) => setNodeSelectionState(node, true));
  emitChange();
};

// 根据ID数组设置选中状态
const setSelectedFromIds = (ids: (string | number)[]) => {
  // 先清空所有选中状态
  internalData.value.forEach((node) => setNodeSelectionState(node, false));

  if (!ids || ids.length === 0) return;

  // 递归查找并设置选中状态
  const findAndSetSelected = (node: CategoryItem): boolean => {
    const nodeId = getNodeId(node);
    const children = getNodeChildren(node);

    // 如果当前节点ID在列表中，选中它
    if (ids.includes(nodeId)) {
      setNodeSelectionState(node, true);
      return true;
    }

    // 如果有子节点，递归检查
    if (children && children.length > 0) {
      let hasSelected = false;
      children.forEach((child: CategoryItem) => {
        if (findAndSetSelected(child)) hasSelected = true;
      });
      return hasSelected;
    }

    return false;
  };

  // 遍历所有顶层节点
  internalData.value.forEach((node) => findAndSetSelected(node));
};

// 监听数据变化
watch(
  () => props.data,
  (newData) => {
    internalData.value = JSON.parse(JSON.stringify(newData));

    // 在数据加载后设置选中状态
    if (props.selectedIds && props.selectedIds.length > 0) {
      setTimeout(() => setSelectedFromIds(props.selectedIds), 0);
    }
  },
  { immediate: true, deep: true }
);

// 监听selectedIds变化
watch(
  () => props.selectedIds,
  (newIds) => {
    if (newIds && newIds.length > 0 && internalData.value.length > 0) {
      setSelectedFromIds(newIds);
    }
  },
  { immediate: true }
);

// 计算各层级显示的数据
const level2Items = computed(() => {
  if (!selectedPath.value[0]) return [];

  const level1Item = internalData.value.find((item) => getNodeId(item) === selectedPath.value[0]);
  return level1Item ? getNodeChildren(level1Item) || [] : [];
});

const level3Items = computed(() => {
  if (!selectedPath.value[0] || !selectedPath.value[1]) return [];

  const level1Item = internalData.value.find((item) => getNodeId(item) === selectedPath.value[0]);
  if (!level1Item || !getNodeChildren(level1Item)) return [];

  const level2Item = getNodeChildren(level1Item).find((item: CategoryItem) => getNodeId(item) === selectedPath.value[1]);
  return level2Item ? getNodeChildren(level2Item) || [] : [];
});

// 节点选择状态检测
const isNodeSelected = (node: CategoryItem): boolean => {
  if (node.selected) return true;

  const children = getNodeChildren(node);
  if (!children || children.length === 0) return false;

  return children.every((child: CategoryItem) => isNodeSelected(child));
};

const isNodeIndeterminate = (node: CategoryItem): boolean => {
  const children = getNodeChildren(node);
  if (!children || children.length === 0) return false;

  const selectedCount = children.filter((child: CategoryItem) => isNodeSelected(child)).length;
  const indeterminateCount = children.filter((child: CategoryItem) => isNodeIndeterminate(child)).length;

  return (selectedCount > 0 && selectedCount < children.length) || indeterminateCount > 0;
};

// 切换节点选中状态
const toggleNodeSelection = (node: CategoryItem) => {
  const newState = !isNodeSelected(node);
  setNodeSelectionState(node, newState);
  emitChange();
};

// 选择分类
const selectCategory = (item: CategoryItem, level: number) => {
  const id = getNodeId(item);

  // 更新选择路径
  selectedPath.value[level] = id;

  // 清除下级路径
  for (let i = level + 1; i < selectedPath.value.length; i++) {
    selectedPath.value[i] = null;
  }
};

// 搜索相关
const handleSearch = () => {
  if (searchText.value) {
    isSearching.value = true;
  } else {
    isSearching.value = false;
  }
};

const clearSearch = () => {
  searchText.value = "";
  isSearching.value = false;
};

// 搜索结果处理
const allSearchResults = computed(() => {
  if (!searchText.value) return [];

  const results: SearchResultItem[] = [];

  internalData.value.forEach((level1) => {
    // 检查一级是否匹配
    if (getNodeName(level1).includes(searchText.value)) {
      results.push({
        id: getNodeId(level1),
        name: getNodeName(level1),
        selected: isNodeSelected(level1),
        categoryName: "",
        isSubItem: false,
        parentRef: level1,
      });
    }

    const children1 = getNodeChildren(level1);
    if (children1 && children1.length > 0) {
      children1.forEach((level2: CategoryItem) => {
        // 检查二级是否匹配
        if (getNodeName(level2).includes(searchText.value)) {
          results.push({
            id: getNodeId(level2),
            name: getNodeName(level2),
            selected: isNodeSelected(level2),
            categoryName: getNodeName(level1),
            isSubItem: true,
            parentRef: level2,
          });
        }

        // 检查三级是否匹配
        const children2 = getNodeChildren(level2);
        if (children2 && children2.length > 0) {
          children2.forEach((level3: CategoryItem) => {
            if (getNodeName(level3).includes(searchText.value)) {
              results.push({
                id: getNodeId(level3),
                name: getNodeName(level3),
                selected: isNodeSelected(level3),
                categoryName: `${getNodeName(level1)} > ${getNodeName(level2)}`,
                isSubItem: true,
                parentRef: level3,
              });
            }
          });
        }
      });
    }
  });

  return results;
});

// 切换搜索结果项选中状态
const toggleSearchResultItem = (item: SearchResultItem) => {
  const newState = !item.selected;
  setNodeSelectionState(item.parentRef, newState);
  item.selected = newState; // 更新UI状态
  emitChange();
};

// 获取选中的结果
const selectedCategories = computed(() => getSelectedItems());
const totalSelectedCount = computed(() => {
  return selectedCategories.value.reduce((total, category) => {
    return total + (category.items.length || 1); // 如果items为空，算1个
  }, 0);
});

// 获取选中的值（用于change事件）
const getSelectedValues = () => {
  const selectedIds: (string | number)[] = [];

  // 递归处理节点，返回节点是否完全选中
  const processNode = (node: CategoryItem): boolean => {
    const children = getNodeChildren(node);

    // 叶子节点
    if (!children || children.length === 0) {
      if (node.selected) {
        selectedIds.push(getNodeId(node));
        return true;
      }
      return false;
    }

    // 处理有子节点的情况
    const childrenSelected = children.map(processNode);
    const allChildrenSelected = childrenSelected.every(Boolean);

    // 根据模式决定返回方式
    if (props.returnMode === "parent" && allChildrenSelected) {
      // 如果所有子节点都被选中且模式为parent，则清除子节点ID，只保留父节点ID
      const nodesToRemove = children.map((child: CategoryItem) => getNodeId(child));

      // 移除已收集的子节点ID
      for (let i = selectedIds.length - 1; i >= 0; i--) {
        if (nodesToRemove.includes(selectedIds[i])) {
          selectedIds.splice(i, 1);
        }
      }

      // 添加父节点ID
      selectedIds.push(getNodeId(node));
    }

    return allChildrenSelected;
  };

  // 处理每个顶层节点
  internalData.value.forEach(processNode);

  return selectedIds;
};

// 恢复原始的 getSelectedItems 方法
const getSelectedItems = (): SelectedResult[] => {
  const result: SelectedResult[] = [];

  // 处理所有节点
  const processAllNodes = (node: CategoryItem, path: string[] = []) => {
    const nodeName = getNodeName(node);
    const currentPath = [...path, nodeName];
    const children = getNodeChildren(node);

    // 叶子节点且被选中
    if ((!children || children.length === 0) && node.selected) {
      const category = currentPath.length > 1 ? currentPath.slice(0, -1).join(" > ") : currentPath[0];
      const existingCategory = result.find((item) => item.category === category);

      if (existingCategory) {
        existingCategory.items.push(nodeName);
      } else {
        if (currentPath.length === 1) {
          result.push({
            category: nodeName,
            items: [], // 空数组表示这是一个没有子项的主分类
          });
        } else {
          result.push({
            category,
            items: [nodeName],
          });
        }
      }
      return;
    }

    // 递归处理子节点
    if (children && children.length > 0) {
      children.forEach((child: CategoryItem) => processAllNodes(child, currentPath));
    }
  };

  internalData.value.forEach((node) => processAllNodes(node));

  return result;
};

// 修改辅助方法确保所有节点状态正确同步
const updateNodeSelectionState = () => {
  // 自下而上更新节点状态
  const updateNodeState = (node: CategoryItem): boolean => {
    const children = getNodeChildren(node);

    // 如果没有子节点，直接返回节点自身的选中状态
    if (!children || children.length === 0) {
      return !!node.selected;
    }

    // 递归更新所有子节点状态，并获取它们的选中状态
    const childStates = children.map((child) => updateNodeState(child));

    // 如果所有子节点都被选中，则设置当前节点为选中
    if (childStates.every((state) => state === true)) {
      node.selected = true;
      return true;
    }
    // 如果所有子节点都未被选中，则设置当前节点为未选中
    else if (childStates.every((state) => state === false)) {
      node.selected = false;
      return false;
    }
    // 部分子节点被选中时，保持当前状态
    else {
      // 这里可以处理部分选中的状态逻辑
      return !!node.selected;
    }
  };

  // 从树的根节点开始更新
  internalData.value.forEach(updateNodeState);
};

// 一个统一的emitChange函数，确保在状态变化时更新节点状态并触发事件
const emitChange = () => {
  // 确保父节点状态与子节点一致
  updateNodeSelectionState();

  // 确保视图更新
  internalData.value = [...internalData.value];

  // 获取所有选中的ID
  const selectedIds = getSelectedValues();
  emit("change", selectedIds);
};

// 对外暴露的方法
const getData = () => getSelectedValues();
const getDetailData = () => ({
  values: getSelectedValues(),
  items: getSelectedItems(),
});

// 暴露方法给父组件
defineExpose({
  getData,
  getDetailData,
  selectAll,
  clearAll,
  setSelectedFromIds,
});

// 初始化默认选中第一个主分类
onMounted(() => {
  if (internalData.value && internalData.value.length > 0) {
    selectedPath.value[0] = getNodeId(internalData.value[0]);
  }
});

// 扁平化所有选中项，用于简单列表显示
const flattenSelectedItems = computed(() => {
  const result: { path: string }[] = [];

  selectedCategories.value.forEach((category) => {
    if (category.items && category.items.length > 0) {
      // 有子项的分类
      category.items.forEach((item) => {
        result.push({
          path: `${category.category} > ${item}`,
        });
      });
    } else {
      // 没有子项的分类
      result.push({
        path: category.category,
      });
    }
  });

  return result;
});

// 根据路径移除选中项
const removeSelectedItemByPath = (path: string, event?: Event) => {
  // 阻止事件冒泡
  if (event) {
    event.stopPropagation();
  }

  const parts = path.split(" > ");

  // 使用更直接的方法查找和取消选中节点
  const deselectByPath = (items: CategoryItem[], pathParts: string[], level: number = 0): boolean => {
    // 遍历当前级别的所有节点
    for (const item of items) {
      const nodeName = getNodeName(item);

      // 当前节点名称匹配路径中的当前部分
      if (nodeName === pathParts[level]) {
        if (level === pathParts.length - 1) {
          // 已经到达路径的最后一部分，设置该节点为未选中

          // 直接修改节点状态
          item.selected = false;

          // 处理子节点状态
          const children = getNodeChildren(item);
          if (children && children.length > 0) {
            children.forEach((child: CategoryItem) => {
              setNodeSelectionState(child, false);
            });
          }

          // 触发视图更新
          internalData.value = [...internalData.value];
          emitChange();
          return true;
        } else {
          // 还没到路径的最后一部分，继续向下查找
          const children = getNodeChildren(item);
          if (children && children.length > 0) {
            if (deselectByPath(children, pathParts, level + 1)) {
              return true;
            }
          }
        }
      }
    }

    return false;
  };

  // 执行取消选择操作
  deselectByPath(internalData.value, parts);
};
</script>

<style lang="less" scoped>
.tree-select-container {
  border: 1px solid #e8e8e8;
  border-radius: 4px;
  overflow: hidden;
  background: #fff;

  .tree-select-header {
    display: flex;
    padding: 10px;
    border-bottom: 1px solid #e8e8e8;

    .search-input {
      flex: 1;
      padding: 8px;
      border: 1px solid #e8e8e8;
      border-radius: 4px;
      outline: none;

      &:focus {
        border-color: #05b44b;
        box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.2);
      }
    }

    .operations {
      display: flex;
      margin-left: 10px;

      button {
        padding: 0 12px;
        height: 32px;
        border: none;
        background-color: #f5f5f5;
        cursor: pointer;
        margin-left: 5px;
        border-radius: 4px;

        &:hover {
          background-color: #e6e6e6;
        }
      }
    }
  }

  .tree-content {
    display: flex;
    height: 360px;

    .dynamic-tree-area {
      display: flex;
      height: 100%;

      .tree-column {
        flex: 1;
        min-width: 150px;
        overflow-y: auto;
        border-right: 1px solid #e8e8e8;

        &:last-child {
          border-right: none;
        }

        &::-webkit-scrollbar {
          width: 6px;
        }

        &::-webkit-scrollbar-thumb {
          background-color: #ccc;
          border-radius: 3px!important;
        }

        .category-item {
          padding: 8px 10px;
          display: flex;
          align-items: center;
          justify-content: space-between;
          cursor: pointer;

          &:hover {
            background-color: #f5f5f5;
          }

          &.active {
            background-color: #e6f7ff;
          }

          .checkbox-label {
            display: flex;
            align-items: center;
            cursor: pointer;
            line-height: 1;

            /* 调整复选框与文字间距和对齐 */
            :deep(.ant-checkbox-wrapper) {
              display: flex;
              align-items: center;
            }

            :deep(.ant-checkbox) {
              margin-right: 8px;
              top: 0;
            }

            /* 文本垂直居中 */
            > span {
              display: inline-block;
              vertical-align: middle;
              line-height: normal;
            }

            /* 搜索结果中的复选框对齐 */
            &:deep(.ant-checkbox + span) {
              padding-top: 0;
              padding-bottom: 0;
            }
          }

          .arrow {
            color: #999;
            font-size: 12px;
          }
        }
      }
    }

    // 右侧已选择区域样式优化
    .selected-area {
      border-left: 1px solid #e8e8e8;
      background: #f9f9f9;
      display: flex;
      flex-direction: column;
      height: 100%;

      .selected-header {
        padding: 10px;
        font-weight: 500;
        border-bottom: 1px solid #e8e8e8;
        background-color: #ffffff;
        display: flex;
        justify-content: space-between;

        .selected-count {
          color: #05b44b;
          margin-left: 5px;
        }

        .clear-btn {
          cursor: pointer;
          color: #05b44b;
          font-size: 12px;
          font-weight: normal;

          &:hover {
            color: #087032;
          }
        }
      }

      .selected-list {
        flex: 1;
        overflow-y: auto;
        padding: 5px 0;
        height: calc(100% - 41px); /* 41px是header的高度加上边框 */

        &::-webkit-scrollbar {
          width: 6px;
        }

        &::-webkit-scrollbar-thumb {
          background-color: #ccc;
          border-radius: 3px;
        }

        .empty-tip {
          padding: 20px;
          text-align: center;
          color: #999;
        }

        // 简单列表样式
        .selected-items {
          .selected-item {
            display: flex;
            justify-content: space-between;
            align-items: center;
            padding: 8px 10px;
            cursor: default;
            border-bottom: 1px solid #f0f0f0;

            &:hover {
              background-color: #f5f5f5;
            }

            .item-name {
              color: #333;
              font-size: 13px;
              flex: 1;
            }

            .remove-icon {
              color: #05b44b;
              font-size: 12px;
              cursor: pointer;
              visibility: visible;
              background-color: #f0fbf5;
              border: 1px solid #b7e8c9;
              width: 16px;
              height: 16px;
              display: flex;
              align-items: center;
              justify-content: center;
              border-radius: 50%;
              margin-left: 8px;

              &:hover {
                color: #ffffff;
                background-color: #05b44b;
                border-color: #05b44b;
              }
            }
          }
        }
      }
    }
  }

  /* 添加搜索结果样式 */
  .search-results {
    height: 360px;
    display: flex;
    flex-direction: column;

    .search-results-header {
      display: flex;
      justify-content: space-between;
      padding: 10px;
      font-weight: 500;
      border-bottom: 1px solid #e8e8e8;
      background-color: #ffffff;

      .search-title {
        .result-count {
          color: #05b44b;
          margin-left: 5px;
        }
      }

      .close-search {
        cursor: pointer;
        color: #999;
        font-size: 16px;

        &:hover {
          color: #f5222d;
        }
      }
    }

    .search-results-content {
      flex: 1;
      overflow-y: auto;

      .empty-tip {
        padding: 20px;
        text-align: center;
        color: #999;
      }

      .search-result-item {
        padding: 8px 10px;
        border-bottom: 1px solid #f0f0f0;

        &:hover {
          background-color: #f5f5f5;
        }

        .checkbox-label {
          display: flex;
          width: 100%;
          cursor: pointer;

          .result-item-content {
            margin-left: 8px;
            display: flex;
            align-items: center;

            .category-path {
              color: #666;
              font-size: 13px;
            }

            .path-separator {
              margin: 0 5px;
              color: #999;
            }

            .highlight {
              color: #333;

              &.main-category {
                font-weight: 500;
              }
            }
          }
        }
      }
    }
  }
}
</style>
